package com.zzyl.nursing.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.service.IDeviceDataService;
import com.zzyl.nursing.service.IDeviceService;
import com.zzyl.nursing.vo.IotMsgNotifyData;
import com.zzyl.nursing.vo.IotMsgService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 设备数据信息Service业务层处理
 *
 * @author kangdi
 * @date 2025-05-25
 */
@Slf4j
@Service
public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceData> implements IDeviceDataService {
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    /**
     * 查询设备数据信息
     *
     * @param id 设备数据信息主键
     * @return 设备数据信息
     */
    @Override
    public DeviceData selectDeviceDataById(Long id) {
        return getById(id);
    }

    /**
     * 查询设备数据信息列表
     *
     * @param deviceData 设备数据信息
     * @return 设备数据信息
     */
    @Override
    public List<DeviceData> selectDeviceDataList(DeviceData deviceData) {
        return deviceDataMapper.selectDeviceDataList(deviceData);
    }

    /**
     * 新增设备数据信息
     *
     * @param deviceData 设备数据信息
     * @return 结果
     */
    @Override
    public int insertDeviceData(DeviceData deviceData) {
        return save(deviceData) ? 1 : 0;
    }

    /**
     * 修改设备数据信息
     *
     * @param deviceData 设备数据信息
     * @return 结果
     */
    @Override
    public int updateDeviceData(DeviceData deviceData) {
        return updateById(deviceData) ? 1 : 0;
    }

    /**
     * 批量删除设备数据信息
     *
     * @param ids 需要删除的设备数据信息主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除设备数据信息信息
     *
     * @param id 设备数据信息主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataById(Long id) {
        return removeById(id) ? 1 : 0;
    }


    /**
     * 处理上报消息,保存到device_data
     *
     * @param contentStr
     */
    @Autowired
    private IDeviceService deviceService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleMessage(String contentStr) {
        //1.判断数据是否为空
        if (StringUtils.isBlank(contentStr)) {
            return;
        }

        JSONObject message = JSONUtil.parseObj(contentStr);
        JSONObject notifyDataObj = message.getJSONObject("notify_data");

        if (notifyDataObj == null) {
            return;
        }

        JSONObject header = notifyDataObj.getJSONObject("header");
        JSONObject body = notifyDataObj.getJSONObject("body");

        if (header == null || body == null) {
            return;
        }

        IotMsgNotifyData notifyData = JSONUtil.toBean(notifyDataObj, IotMsgNotifyData.class);
        String deviceId = notifyData.getHeader().getDeviceId();//设备id
        //判断设备是否存在
        Device device = deviceService.lambdaQuery()
                .eq(Device::getIotId, deviceId)
                .one();
        if (device==null){
            throw new BaseException("查不到这个设备");
        }
        //3.对数据进行封装
        List<IotMsgService> serviceList = notifyData.getBody().getServices();

        List<DeviceData> deviceDataList = new ArrayList<>();//收集的容器

        serviceList.forEach(x->{
            //获取设备上报时间
            String eventTime = x.getEventTime();
            LocalDateTime alarmTime = OffsetDateTime.parse(eventTime, DateTimeFormatter
                            .ofPattern("yyyyMMdd'T'HHmmssX"))
                    .atZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();

            Map<String, Object> properties = x.getProperties();
            properties.forEach((k,v)->{
                DeviceData deviceData = new DeviceData();
                BeanUtils.copyProperties(device,deviceData);
                deviceData.setId(null);//上面会把id拷贝上，让mybatisPlus自己生成
                deviceData.setFunctionId(k);//功能名（设备物模型属性名）
                deviceData.setDataValue(String.valueOf(v));//物模型属性值
                deviceData.setAlarmTime(alarmTime);//上报时间
                deviceData.setAccessLocation(device.getBindingLocation());//绑定位置
                deviceDataList.add(deviceData);//处理一条加一条数据
            });
        });
        //4.批量保存数据
        if(CollUtil.isNotEmpty(deviceDataList)){
            boolean result = this.saveBatch(deviceDataList);
            if(!result){
                throw new BaseException("批量添加到表失败");
            }
            log.info("批量保存设备数据成功，本次保存成功{}条",deviceDataList.size());
        }
    }
}
